﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Bewise.SmartIndexManager.Core.Classes.Operations;
using Bewise.SmartIndexManager.Core.Classes.Options;
using Bewise.SmartIndexManager.Core.Classes.Database;
using Microsoft.SqlServer.Management.Common;
using System.Data.SqlClient;
using Microsoft.SqlServer.Management.Smo;
using System.Data;

namespace Bewise.SmartIndexManager.Core.Classes.IndexManager
{
    public static class IndexManager
    {
        // delegué chargé d'appeler le log SSIS
        public static Action<string, DateTime, DateTime> LogSSIS_OnInformation;

        // Référence vers les informations issues de l'IHM
        private static TaskInfosContainer TaskInfosContainer { get; set; }

        public static void Execute(TaskInfosContainer taskInfosContainer)
        {
            if (taskInfosContainer == null)
                throw new ArgumentNullException("taskInfosContainer");

            // récupération du contexte des informations contenues dans l'IHM
            TaskInfosContainer = taskInfosContainer;

            // récupération du seuil de fragmentation
            var seuil = taskInfosContainer.Options.OfType<SeuilIndexOption>().FirstOrDefault();
            if (seuil != null)
                IndexManagerOperations.IndexFillFactorSeuil = seuil.IndexSeuilFragmentation;

            using (var connection =
                new SqlConnection(TaskInfosContainer.ConnectionString))
            {
                if (connection.State != ConnectionState.Open)
                    connection.Open();

                // connection au serveur
                var serverConnection = new ServerConnection(connection);
                var server = new Server(serverConnection);

                var now = DateTime.Now;

                // récupération des bases de données a traiter
                foreach (var database in GetEntities.GetDatabases(TaskInfosContainer, server))
                {
                    // écriture dans le Log SSIS "OnInformation"
                    IndexManager.LogSSIS_OnInformation(string.Format("Database Target : {0}", database.Name), now, now);

                    // test Si options Database respectées
                    foreach (DatabaseOption option in TaskInfosContainer.Options.OfType<DatabaseOption>())
                    {
                        option.DatabaseSource = database;
                        // test si base de données courante est valide pour le traitement
                        if (!option.CheckValidation())
                        {
                            IndexManager.LogSSIS_OnInformation(option.OptionDescription(), now, now);
                            break;
                        }
                    }

                    // boucle sur les tables
                    foreach (Table table in database.Tables)
                    {
                        foreach (Index index in table.Indexes)
                        {
                            // test des options
                            foreach (IndexOption option in TaskInfosContainer.Options.OfType<IndexOption>())
                            {
                                option.IndexSource = index;
                                // test si Index courant est valide pour le traitement
                                if (!option.CheckValidation())
                                {
                                    IndexManager.LogSSIS_OnInformation(option.OptionDescription(), now, now);
                                    break;
                                }
                            }

                            // récupération de l'objet operation associé à la situation de l'index en cours
                            var operation = IndexManagerOperations.Create(index);
                            operation.StartDateTime = DateTime.Now;

                            // operation de maintenance sur l'index en cours.
                            operation.OperationIndex();
                            
                            operation.FinishDateTime = DateTime.Now;
                            
                            // Log action terminée
                            IndexManager.LogSSIS_OnInformation(operation.OperationDescription(), operation.StartDateTime, operation.FinishDateTime);
                        }
                    }
                }
            }
        }
    }
}
